package com.hwtx.form.domain.handle.i18n;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.collect.Lists;
import com.hwtx.form.domain.handle.FormI18nHandle;
import com.hwtx.form.util.FileMonitor;
import com.hwtx.form.util.JacksonUtil;
import io.geekidea.boot.config.properties.BootProperties;
import io.geekidea.boot.framework.exception.BusinessException;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.hwtx.form.util.JacksonUtil.json2Object;
import static io.geekidea.boot.common.constant.SystemConstant.I18N_CONFIG_FILE;

@Component
@Slf4j
@Getter
public class I18nConfig {
    @Resource
    private BootProperties bootProperties;
    @Resource
    private MessageSource messageSource;

    @JsonDeserialize(using = String2ArrayDeserializer.class)
    private List<String[]> group;

    public String handlePageI18n(String content, Locale locale) {
        if (StringUtils.isBlank(content)) {
            return content;
        }
        JsonNode root = JacksonUtil.readJson(content);
        if (root == null) {
            throw new BusinessException("页面内容解析异常");
        }
        FormI18nHandle.handle(root, messageSource, getGroup(), locale);
        return root.toPrettyString();
    }

    @PostConstruct
    public void setup() throws Exception {
        if (bootProperties.getForm().getI18n() != null &&
                bootProperties.getForm().getI18n().isEnableI18nConfigReload()) {
            File dir = new File(Objects.requireNonNull(getClass().getClassLoader().getResource("i18n")).getFile());
            FileAlterationObserver observer = getFileAlterationObserver(dir);
            FileMonitor fileMonitor = new FileMonitor();
            fileMonitor.start(5, observer);
            I18nConfig i18nConfig = json2Object(FileUtils.readFileToString(new File(Objects.requireNonNull(getClass().getClassLoader()
                    .getResource("i18n/" + I18N_CONFIG_FILE)).getFile()), StandardCharsets.UTF_8), I18nConfig.class);
            if (i18nConfig == null || i18nConfig.getGroup() == null) {
                throw new BusinessException("国际化配置文件解析异常");
            }
            this.group = i18nConfig.getGroup();
        }
    }

    @NotNull
    private FileAlterationObserver getFileAlterationObserver(File dir) {
        FileAlterationObserver observer = new FileAlterationObserver(dir, pathname -> Objects.equals(pathname.getName(), I18N_CONFIG_FILE));
        observer.addListener(new FileAlterationListenerAdaptor() {
            @Override
            public void onFileChange(File file) {
                try {
                    I18nConfig i18nConfig = json2Object(FileUtils.readFileToString(file, StandardCharsets.UTF_8), I18nConfig.class);
                    if (i18nConfig == null || i18nConfig.getGroup() == null) {
                        throw new BusinessException("国际化配置文件解析异常");
                    }
                    I18nConfig.this.group = i18nConfig.getGroup();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        return observer;
    }

    static class String2ArrayDeserializer extends JsonDeserializer<List<String[]>> {
        @Override
        public List<String[]> deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException {
            String[] rawData = p.readValueAs(String[].class);
            if (rawData != null) {
                return Arrays.stream(rawData).map(data -> StringUtils.split(data, ",")).collect(Collectors.toList());
            }
            return Lists.newArrayList();
        }
    }
}
